﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Draco.OWF.Studio.Designer
{
    /// <summary>
    /// Interaction logic for Ruler.xaml
    /// </summary>
    public partial class Ruler : Canvas
    {
        private Point m_Origin = new Point(0,0);
        private double m_zoom = 1;

        private int m_minScale = 10;
        private int m_MaxScale = 50;

        /// <summary>
        /// Get or set origin
        /// </summary>
        public Point Origin 
        { 
            get { return m_Origin; } 
            set 
            {
                if (m_Origin.X != value.X || m_Origin.Y != value.Y)
                {
                    m_Origin = value;
                    DrawRule();     //redraw it
                    //if (this.Direction == Direction.Horizontal)
                    //    Canvas.SetLeft(this.RuleCanvas,m_Origin.X);
                    //else
                    //    Canvas.SetTop(this.RuleCanvas, m_Origin.Y);
                }
                
            } 
        }

        /// <summary>
        /// constructor
        /// </summary>
        public Ruler()
        {
            InitializeComponent();
        }

        #region DependencyProperty
        public static readonly DependencyProperty DirectionProperty = DependencyProperty.Register(
            "Direction", typeof(Direction), typeof(Ruler), new FrameworkPropertyMetadata());
        public Direction Direction
        {
            get { return (Direction)GetValue(DirectionProperty); }
            set { SetValue(DirectionProperty, value); }
        }
        #endregion
        
        private void Canvas_Loaded(object sender, RoutedEventArgs e)
        {
            DrawRule();
        }
        private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            DrawRule();
        }

        private void DrawRule()
        {
            if (this.Visibility == System.Windows.Visibility.Visible)
            {
                if (this.Direction == Direction.Horizontal)
                    DrawHorizontalRule(m_Origin, m_zoom);
                else
                    DrawVerticalRule(m_Origin, m_zoom);
            }
        }

        #region Horizontal
        protected void DrawHorizontalRule(Point origin, double zoom)
        {
            this.RuleCanvas.Children.Clear();
            Line baseLine = CreateLine(new Point(0, 0), new Point(this.ActualWidth, 0), 0.1, Brushes.Black);
            this.RuleCanvas.Children.Add(baseLine);
            for (double pix = 0; pix < this.ActualWidth; pix++)
            {
                long scaleNumber = GetHorizontalNumber(pix, origin, zoom);
                if (scaleNumber % m_MaxScale == 0)
                {
                    Line scaleLine = CreateLine(new Point(pix,0),new Point(pix,20),0.1,Brushes.Black);
                    //number
                    Label lab = new Label();
                    lab.Content = scaleNumber;
                    lab.FontSize = 10;
                    this.RuleCanvas.Children.Add(lab);
                    Canvas.SetTop(lab, 5);
                    Canvas.SetLeft(lab, pix + 1);
                    this.RuleCanvas.Children.Add(scaleLine);
                }
                else if(scaleNumber % m_minScale == 0)
                {
                    Line scaleLine = CreateLine(new Point(pix,0),new Point(pix,10),0.1,Brushes.Black);
                    this.RuleCanvas.Children.Add(scaleLine);
                }
            }
        }
        private long GetHorizontalNumber(double x, Point origin, double zoom)
        {
            return Convert.ToInt64(Math.Floor((x + origin.X) * zoom));
        }
        #endregion

        #region Vertical
        protected void DrawVerticalRule(Point origin, double zoom)
        {
            this.RuleCanvas.Children.Clear();
            Line baseLine = CreateLine(new Point(0, 0), new Point(0, this.ActualHeight), 0.1, Brushes.Black);
            this.RuleCanvas.Children.Add(baseLine);
            for (double pix = 0; pix < this.ActualHeight; pix ++)
            {
                long scaleNumber = GetVerticalNumber(pix, origin, zoom);
                if (scaleNumber % m_MaxScale == 0)
                {
                    Line scaleLine = CreateLine(new Point(0, pix), new Point(20, pix), 0.1, Brushes.Black);
                    if (pix != 0)
                    {
                        //number
                        Label lab = new Label();
                        lab.Content = scaleNumber;
                        lab.FontSize = 10;
                        this.RuleCanvas.Children.Add(lab);
                        Canvas.SetTop(lab, pix + 1);
                        Canvas.SetLeft(lab, 5);
                        lab.RenderTransform = new RotateTransform(270);
                    }
                    this.RuleCanvas.Children.Add(scaleLine);
                }
                else if (scaleNumber % m_minScale == 0)
                {
                    Line scaleLine = CreateLine(new Point(0, pix), new Point(10, pix), 0.1, Brushes.Black);
                    this.RuleCanvas.Children.Add(scaleLine);
                }
            }
            Line lastLine = CreateLine(new Point(0, this.ActualHeight), new Point(25, this.ActualHeight), 0.1, Brushes.Black);
            this.RuleCanvas.Children.Add(lastLine);
        }
        private long GetVerticalNumber(double y, Point origin, double zoom)
        {
            return Convert.ToInt64(Math.Floor((y + origin.Y) * zoom));
        }
        #endregion

        private Line CreateLine(Point start, Point end, double thickness,SolidColorBrush brush)
        {
            Line newLine = new Line();
            newLine.StrokeThickness = thickness;
            newLine.Stroke = brush;
            newLine.X1 = start.X; newLine.Y1 = start.Y; newLine.X2 = end.X; newLine.Y2 = end.Y;
            return newLine;
        }
    }
}
